package com.cnvp.dbcompare.controller;

import com.cnvp.dbcompare.pojo.bo.CheckReportBo;
import com.cnvp.dbcompare.biz.MainBiz;
import com.cnvp.dbcompare.constant.SystemConstant;
import com.cnvp.dbcompare.constant.enums.RegulationCheckTypeEnum;
import com.cnvp.dbcompare.pojo.bo.DifferentReportBo;
import com.cnvp.dbcompare.pojo.cache.CommonData;
import com.cnvp.dbcompare.pojo.dto.DatabaseInfoDto;
import com.cnvp.dbcompare.pojo.model.BizException;
import com.cnvp.dbcompare.pojo.model.R;
import com.cnvp.dbcompare.pojo.vo.DatabaseInfoVo;
import com.cnvp.dbcompare.util.Tools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 生成sql的参考：https://gitee.com/bravof/differ
 */

/**
 * 主要的控制器
 * @author suqiongbang
 * @date 2020/12/28 20:33
 */
@RestController
@RequestMapping("/api")
public class ApiController {

    @Autowired
    MainBiz mainBiz;

    @GetMapping("/test")
    public R<Boolean> test() {
        return R.ok(true);
    }

    @GetMapping("/list")
    public R<List<DatabaseInfoDto>> list() {
        return R.ok(CommonData.databaseInfoList);
    }

    @GetMapping("/listRegulationCheckType")
    public R<List<Map<String, String>>> listRegulationCheckType() {
        List<Map<String, String>> resultList = new ArrayList<>();
        for (RegulationCheckTypeEnum regulationCheckTypeEnum : RegulationCheckTypeEnum.values()) {
            Map<String, String> result = new HashMap<>(4);
            result.put("code", regulationCheckTypeEnum.getCode());
            result.put("desc", regulationCheckTypeEnum.getDesc());
            resultList.add(result);
        }
        return R.ok(resultList);
    }

    @GetMapping("/getIgnoreWords")
    public R<String> getIgnoreWords(String code) {
        if (RegulationCheckTypeEnum.NAME_ERROR_SPELL.getCode().equals(code)) {
            return R.ok(CommonData.ignoreSpellingWordStr);
        } else if (RegulationCheckTypeEnum.TABLE_NAME_CONTAIN_PLURALITY.getCode().equals(code)) {
            return R.ok(CommonData.ignorePluralizeWordStr);
        }
        return R.ok();
    }

    @PostMapping("/save")
    public R<Boolean> save(@RequestBody DatabaseInfoVo databaseInfoVo) {
        if (databaseInfoVo.getKey() == null) {
            DatabaseInfoDto target = new DatabaseInfoDto();
            BeanUtils.copyProperties(databaseInfoVo, target);
            target.setKey(CommonData.databaseInfoList.size());
            CommonData.databaseInfoList.add(target);
        } else {
            DatabaseInfoDto databaseInfoDto = CommonData.databaseInfoList.get(databaseInfoVo.getKey());
            BeanUtils.copyProperties(databaseInfoVo, databaseInfoDto);
        }
        Tools.setCacheData(SystemConstant.FilePath.DATABASE_INFO_DATA_FILE_NAME, CommonData.databaseInfoList);
        return R.ok(true);
    }

    @PostMapping("/saveIgnoreWords")
    public R<Boolean> saveIgnoreWords(@RequestBody Map<String, Object> param) {
        String code = (String) param.get("code");
        String ignoreWords = (String) param.get("ignoreWords");
        if (RegulationCheckTypeEnum.NAME_ERROR_SPELL.getCode().equals(code)) {
            if (ignoreWords != null && !CommonData.ignoreSpellingWordStr.equals(ignoreWords)) {
                CommonData.ignoreSpellingWordStr = ignoreWords;
                Tools.setCacheData(SystemConstant.FilePath.IGNORE_SPELLING_WORDS_DATA_FILE_NAME, CommonData.ignoreSpellingWordStr);
            }
        } else if (RegulationCheckTypeEnum.TABLE_NAME_CONTAIN_PLURALITY.getCode().equals(code)) {
            if (ignoreWords != null && !CommonData.ignorePluralizeWordStr.equals(ignoreWords)) {
                CommonData.ignorePluralizeWordStr = ignoreWords;
                Tools.setCacheData(SystemConstant.FilePath.IGNORE_PLURALIZE_WORDS_DATA_FILE_NAME, CommonData.ignorePluralizeWordStr);
            }
        }
        return R.ok(true);
    }

    @GetMapping("/delete")
    public R<Boolean> delete(Integer key) {
        if (key != null && key >= 0 && key < CommonData.databaseInfoList.size()) {
            try {
                CommonData.databaseInfoList.remove(key.intValue());
                Tools.setCacheData(SystemConstant.FilePath.DATABASE_INFO_DATA_FILE_NAME, CommonData.databaseInfoList);
            } catch (Exception e) {
                throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "删除失败");
            }
        }
        return R.ok(true);
    }

    @GetMapping("/getReport")
    public R<DifferentReportBo> getReport(Integer changeKey, Integer targetKey) {
        this.checkParam(changeKey, targetKey);
        DifferentReportBo differentReport;
        try {
            differentReport = mainBiz.getDifferentReport(changeKey, targetKey);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(HttpStatus.BAD_REQUEST, "操作失败");
        }
        return R.ok(differentReport);
    }

    @GetMapping("/getSql")
    public R<List<String>> getSql(Integer changeKey, Integer targetKey) {
        this.checkParam(changeKey, targetKey);
        List<String> sql = mainBiz.getDifferentSql(changeKey, targetKey);
        return R.ok(sql);
    }

    @GetMapping("/getCheck")
    public R<Collection<CheckReportBo>> getCheck(Integer changeKey, String checkIds) {
        if (changeKey == null || changeKey.intValue() < 0 || changeKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "变动库的数据库连接信息无效");
        }
        if (StringUtils.isEmpty(checkIds)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "检查项不能为空");
        }
        Collection<CheckReportBo> checkReportBoList = mainBiz.regulationCheck(changeKey, checkIds);
        return R.ok(checkReportBoList);
    }

    /**
     * 检查参数是否合法
     * @param changeKey 变动库key
     * @param targetKey 目标库key
     */
    private void checkParam(Integer changeKey, Integer targetKey){
        if (changeKey == null || changeKey.intValue() < 0 || changeKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "变动库的数据库连接信息无效");
        }
        if (targetKey == null || targetKey.intValue() < 0 || targetKey.intValue() >= CommonData.databaseInfoList.size()) {
            throw new BizException(HttpStatus.BAD_REQUEST, "目标库的数据库连接信息无效");
        }
        if (changeKey.equals(targetKey)) {
            throw new BizException(HttpStatus.BAD_REQUEST, "数据库连接信息不能一样");
        }
    }
}
